package org.andes.kownledge.operator.executable;

import java.util.ArrayList;
import java.util.List;

import org.andes.base.Bindings;
import org.andes.base.Unification;
import org.andes.kownledge.operator.Executable;
import org.andes.kownledge.operator.NoAtom;
import org.andes.kownledge.operator.Term;
import org.andes.sgg.st;

public class AnyMember extends Executable{

//	;;; The executable (Any-member <term> <set>) expects <set> to be a
//	;;; list of terms when bindings are substituted into it.  It returns a
//	;;; set of states, one for each member of the list that the given
//	;;; <term> unifies with, with the variable in the term bound to the
//	;;; member.
//
//	(defun execute-any-member (Ex State)
//	  "Returns a set of states, one for each member of the third element of 
//	   (any-member <term> <set>) that unifies with the given second element."
//	  (let ((Term (second Ex))
//		(TermSet (subst-bindings (st-bindings State) (third Ex)))
//	        (bindings)  (NewState)  (successors))
//	    (unless (listp TermSet) (error "Non-list ~A given to any member" TermSet))
//	    (dolist (Value TermSet)
//	      (when (setq bindings (unify Term Value (st-bindings State)))
//		(setq NewState (copy-st State))      
//		(setf (st-bindings NewState) bindings)
//		(push NewState Successors))) 
//	    (nreverse Successors)))
	@Override
	public List<st> exec(st state) {
		List<Term> newset=new ArrayList<Term>();
		List<st> Successors=new ArrayList<st>();
		for(Term term:set){
			newset.add(term.substBindings(state.getBindings()));
		}
		for(Term value:newset){
			Bindings bindings=Unification.unify(term, value, state.getBindings());
			if(bindings!=null){
				st newstate=state.copy();
				newstate.setBindings(bindings);
				Successors.add(newstate);
				
			}
		}
		return Successors;
	}

	Term term;
	public void setTerm(Term term){
		this.term=term;
	}

	private List<Term> set=new ArrayList<Term>();
	public void addSetElem(Term elem){
		this.set.add(elem);
	}
	@Override
	public Term substBindings(Bindings bindings) {
		AnyMember result=new AnyMember();
		result.setTerm(term.substBindings(bindings));
		for(Term fun:set){
			result.addSetElem(fun.substBindings(bindings));
		}
		return result;
	}
	 
}
